_Pragma("once");

#include <ctime>
#include <cstring>
#include <string_view>

#include "LoopStatus.h"
#include "DateTimeUtility.h"
#include "LoopCommandType.h"
#include "HalUtility.h"


struct LoopControlInfo {
    LoopSize_t length;

    DateTimeUtility::ClockTime_t beginTime = DateTimeUtility::ClockTime_t::zero();
    DateTimeUtility::ClockTime_t duration = DateTimeUtility::ClockTime_t::zero();
    LoopCommandType commandType = LoopCommandType::OFFLINE_COMMAND;
    LoopStatus loopStatus[];


    LoopControlInfo(const LoopSize_t& length) {
        this->length = length;
    }

    LoopControlInfo(const LoopSize_t& length, const LoopStatus& initialStatus) {
        this->length = length;
        setCommand(initialStatus);
    }

    LoopControlInfo(const LoopStatus* const statusArray, const LoopSize_t& length) {
        this->length = length;

        setCommand(statusArray, length);
    }

    LoopControlInfo(const LoopControlInfo& other) {
//        this->length = other.length;
//        this->beginTime = other.beginTime;
//        this->duration = other.duration;
//        this->commandType = other.commandType;
        std::memcpy(reinterpret_cast<void*> (this), &other, computeByteSize(other.length));
    }

    void setCommand(const LoopStatus& status) {
        std::memset(this->loopStatus, status, length);
    }

    void setCommand(const LoopStatus* const statusArray, const LoopSize_t& length) {
        std::memcpy(this->loopStatus, statusArray, length);
    }


     operator std::string_view(){
        return std::string_view(reinterpret_cast<std::string_view::pointer>(loopStatus), length);
     }


    const LoopControlInfo* next() const {
        const uint8_t* pRaw = reinterpret_cast<const uint8_t*> (this);

        const uint8_t* pNext = pRaw + computeByteSize(length);


        return reinterpret_cast<const LoopControlInfo*> (pNext);
    }


    LoopControlInfo* next() {
        uint8_t* pRaw = reinterpret_cast<uint8_t*> (this);

        uint8_t* pNext = pRaw + computeByteSize(length);


        return reinterpret_cast<LoopControlInfo*> (pNext);
    }

    static size_t computeByteSize(uint32_t length) {
        return sizeof (LoopControlInfo) + sizeof (LoopStatus) * length;
    }

    static void* operator new(size_t size, LoopSize_t length);

    static void operator delete(void* data, void* placement);//todo


    static void releaseMemory(LoopControlInfo* pControlInfo);
    //  static void *operator new(size_t, void*);
};



using LoopControlInfoPtr = std::shared_ptr<LoopControlInfo>;



template<class charT>
std::basic_ostream<charT>&  operator << (std::basic_ostream<charT>& stream, const LoopControlInfo& loopControlInfo) {
    stream << "length:" << loopControlInfo.length;
    std::string timeString;
    stream << ",beginTime:" << DateTimeUtility::tmFormatToString(DateTimeUtility::toTm(DateTimeUtility::toTime_t(loopControlInfo.beginTime)), DateTimeUtility::DATE_TIME_FOR_READ_FORMAT, timeString);
    stream << ",duration:" << DateTimeUtility::toTime_t(loopControlInfo.duration);
    stream << ",commandType:" << static_cast<char>(loopControlInfo.commandType);
    stream << ",loopStatus:" << std::string_view(reinterpret_cast <std::string_view::const_pointer>(loopControlInfo.loopStatus), loopControlInfo.length);

    return stream;
}








